package cc.uncarbon.module.appapi.service;

import cc.uncarbon.framework.core.context.UserContext;
import cc.uncarbon.framework.core.context.UserContextHolder;
import cc.uncarbon.framework.core.exception.BusinessException;
import cc.uncarbon.framework.core.page.PageParam;
import cc.uncarbon.framework.core.page.PageResult;
import cc.uncarbon.module.appapi.mapper.*;
import cc.uncarbon.module.appapi.model.request.OrdersDTO;
import cc.uncarbon.module.appapi.model.request.OrderListDTO;
import cc.uncarbon.module.appapi.model.response.OrdersItemBO;
import cc.uncarbon.module.appapi.model.response.OrdersTimeBO;
import cc.uncarbon.module.appapi.model.vo.OrdersDetailVO;
import cc.uncarbon.module.appapi.model.vo.OrdersVO;
import cc.uncarbon.module.appapi.util.OrderNumberGenerator;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import com.wechat.pay.java.service.refund.model.Status;
import com.yanrumiao.entity.*;
import com.yanrumiao.enumns.OrdersStatusEnum;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RequiredArgsConstructor
@Service
@Slf4j
public class OrdersService {

    private final OrdersMapper ordersMapper;
    private final ItemMapper itemMapper;
    private final OrdersItemMapper ordersItemMapper;
    private final StaffMapper staffMapper;
    private final WechatPayService wechatPayService;
    private final PaymentService paymentService;
    private final ItemService itemService;
    private final StoreMapper storeMapper;
    private StoreEntity store;


    public Long createOrder(OrdersDTO dto) {
        OrdersEntity entity = new OrdersEntity();
        BeanUtil.copyProperties(dto, entity);
        String orderNo = OrderNumberGenerator.generateOrderNumber();

        UserContext userContext = UserContextHolder.getUserContext();
        entity.setOrderNo(orderNo);
        entity.setUserId(userContext.getUserId());
        entity.setStatus(OrdersStatusEnum.ORDER_NOPAY);
        ordersMapper.insert(entity);
        return entity.getId();
    }

    public OrdersEntity getOrdersById(Long id) {
        return ordersMapper.selectById(id);
    }

    public OrdersEntity getOrderByNo(String outTradeNo) {
        LambdaQueryWrapper<OrdersEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrdersEntity::getOrderNo, outTradeNo);
        return ordersMapper.selectOne(queryWrapper);
    }

    public void updateOrderStatus(Long id, OrdersStatusEnum status) {
        OrdersEntity entity = ordersMapper.selectById(id);
        entity.setStatus(status);
        ordersMapper.updateById(entity);
    }

    public PageResult<OrdersVO> getordersList(PageParam pageParam, OrderListDTO dto) {
        if (store == null) {
            store = storeMapper.selectById(dto.getStoreId());
        }
        Page<OrdersEntity> entityPage = ordersMapper.selectPage(
                new Page<>(pageParam.getPageNum(), pageParam.getPageSize()),
                new QueryWrapper<OrdersEntity>()
                        .lambda()
                        .eq(dto.getStatus() != OrdersStatusEnum.ORDER_ALL, OrdersEntity::getStatus, dto.getStatus())
                        .eq(ObjectUtil.isNotNull(dto.getStoreId()), OrdersEntity::getStoreId, dto.getStoreId())
                        .eq(OrdersEntity::getUserId, UserContextHolder.getUserContext().getUserId())
                        .orderByDesc(OrdersEntity::getCreatedAt)

        );
        return this.entityPage2BOPage(entityPage);
    }

    /**
     * 实体分页转 BO 分页
     *
     * @param entityPage 实体分页
     * @return BO 分页
     */
    private PageResult<OrdersVO> entityPage2BOPage(Page<OrdersEntity> entityPage) {
        return new PageResult<OrdersVO>()
                .setCurrent(entityPage.getCurrent())
                .setSize(entityPage.getSize())
                .setTotal(entityPage.getTotal())
                .setRecords(this.entityList2BOs(entityPage.getRecords()));
    }

    /**
     * 实体 List 转 BO List
     *
     * @param entityList 实体 List
     * @return BO List
     */
    private List<OrdersVO> entityList2BOs(List<OrdersEntity> entityList) {
        if (CollUtil.isEmpty(entityList)) {
            return Collections.emptyList();
        }

        // 深拷贝
        List<OrdersVO> ret = new ArrayList<>(entityList.size());
        entityList.forEach(
                entity -> ret.add(this.entity2BO(entity))
        );

        return ret;
    }

    /**
     * 实体转 BO
     *
     * @param entity 实体
     * @return BO
     */
    private OrdersVO entity2BO(OrdersEntity entity) {
        if (entity == null) {
            return null;
        }
        if (entity.getStatus() == OrdersStatusEnum.ORDER_NOPAY) {
            Transaction transaction = wechatPayService.queryOrderById(entity, store);
            if (transaction != null) {
                switch (transaction.getTradeState()){
                    case SUCCESS:
                        paymentService.updatePaymentStatusByOrderNo(entity.getOrderNo(), 1);
                        updateOrdersStatus(entity.getOrderNo(), OrdersStatusEnum.ORDER_PAY);
                        break;
                    case CLOSED:
                        paymentService.updatePaymentStatusByOrderNo(entity.getOrderNo(), -1);
                        updateOrdersStatus(entity.getOrderNo(), OrdersStatusEnum.ORDER_CLOSE);
                        break;
                }
            }

        }
        OrdersVO bo = new OrdersVO();
        entity = ordersMapper.selectById(entity.getId());
        BeanUtil.copyProperties(entity, bo);
        ItemEntity itemEntity = itemMapper.selectById(entity.getItemId());
        // 可以在此处为BO填充字段
        OrdersItemBO itemBO = new OrdersItemBO();
        BeanUtil.copyProperties(itemEntity, itemBO);
        bo.setItemInfo(itemBO);
        return bo;
    }

    public OrdersDetailVO getOrderDetail(Long id) {
        OrdersEntity entity = ordersMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException(400, "无效订单ID");
        }
        OrdersDetailVO ordersDetailVO = new OrdersDetailVO();
        BeanUtil.copyProperties(entity, ordersDetailVO);
        //查询预约信息
        List<OrdersItemEntity> orderItem = ordersItemMapper.selectList(new LambdaQueryWrapper<OrdersItemEntity>().eq(OrdersItemEntity::getOrderId, id));
        ordersDetailVO.setOrderTimeList(new ArrayList<>());
        if (CollUtil.isNotEmpty(orderItem)) {
            List<OrdersTimeBO> ordersTimeBOList = new ArrayList<>(orderItem.size());
            orderItem.forEach(item -> {
                OrdersTimeBO ordersTimeBO = new OrdersTimeBO();
                BeanUtil.copyProperties(item, ordersTimeBO);
                StaffEntity staff = staffMapper.selectById(item.getStaffId());
                ordersTimeBO.setStatffInfo(staff);
                ordersTimeBOList.add(ordersTimeBO);
            });
            ordersDetailVO.setOrderTimeList(ordersTimeBOList);
        }
        //查询项目信息
        ItemEntity itemEntity = itemMapper.selectById(entity.getItemId());
        OrdersItemBO itemBO = new OrdersItemBO();
        BeanUtil.copyProperties(itemEntity, itemBO);
        ordersDetailVO.setItemInfo(itemBO);
        return ordersDetailVO;
    }

    public void cancelOrder(Long id) {
        OrdersEntity orders = ordersMapper.selectById(id);
        if (orders == null) {
            throw new BusinessException(400, "无效订单ID");
        }
        StoreEntity store = storeMapper.selectById(orders.getStoreId());
        //待预约的退款
        if (orders.getStatus() == OrdersStatusEnum.ORDER_PAY) {
            PaymentEntity payment = paymentService.getPaymentByOrderNo(orders.getOrderNo());

            Status refund = wechatPayService.refund(orders, payment, store);
            if (Status.SUCCESS.equals(refund)) {
                paymentService.updatePaymentStatusByOrderNo(orders.getOrderNo(), 3);
                updateOrdersStatus(orders.getOrderNo(), OrdersStatusEnum.ORDER_REFUND);
            }
        }
        //待付款的取消订单
        if (orders.getStatus() == OrdersStatusEnum.ORDER_NOPAY) {
            wechatPayService.close(orders, store);
            updateOrderStatusByOrderNo(orders.getOrderNo(), OrdersStatusEnum.ORDER_CLOSE);
            paymentService.updatePaymentStatusByOrderNo(orders.getOrderNo(), -1);
        }


    }

    public void updateOrderStatusByOrderNo(String orderNo, OrdersStatusEnum ordersStatusEnum) {

        LambdaQueryWrapper<OrdersEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrdersEntity::getOrderNo, orderNo);
        OrdersEntity orders = ordersMapper.selectOne(queryWrapper);
        if (orders.getStatus() != ordersStatusEnum) {
            orders.setStatus(ordersStatusEnum);
            ordersMapper.updateById(orders);
            log.info("---------修改订单状态成功" + orders.getId());
        }

    }

    //预支付
    public PrepayWithRequestPaymentResponse unifiedOrderV3(Long id) {
        // 获取订单信息
        OrdersEntity orders = ordersMapper.selectById(id);
        if (orders == null) {
            throw new BusinessException(400, "订单无效");
        }
        if (orders.getStatus() != OrdersStatusEnum.ORDER_NOPAY) {
            throw new BusinessException(400, "订单已支付");
        }
        //店铺信息
        StoreEntity storeEntity = storeMapper.selectById(orders.getStoreId());
        //添加支付记录
        paymentService.createPayment(orders, 0);
        //获取项目信息
        ItemEntity itemEntity = itemService.getOneById(orders.getItemId());
        if (itemEntity == null) {
            throw new BusinessException(400, "项目不存在");
        }
        PrepayWithRequestPaymentResponse response = wechatPayService.unifiedOrderV3(orders, itemEntity, storeEntity);
        return response;
    }

    // 支付回调
    public void payNotify(HttpServletRequest request) {
        Transaction transaction = wechatPayService.payNotify(request);
        log.info("---------支付成功的回调---"+transaction.getOutTradeNo() );
        if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
            log.info("---------支付成功的回调----Payment");
            paymentService.updatePaymentStatusByOrderNo(transaction.getOutTradeNo(), 1);
            updateOrdersStatus(transaction.getOutTradeNo(), OrdersStatusEnum.ORDER_PAY);
        }
        if (Transaction.TradeStateEnum.CLOSED.equals(transaction.getTradeState())) {
            log.info("---------支付成功的回调----CLOSED");
            paymentService.updatePaymentStatusByOrderNo(transaction.getOutTradeNo(), -1);
            updateOrdersStatus(transaction.getOutTradeNo(), OrdersStatusEnum.ORDER_CLOSE);
        }
    }

    public void refundNotify(HttpServletRequest request) {
        RefundNotification notification = wechatPayService.refundNotify(request);
        log.info("---------退款成功的回调----CLOSED" + notification);
        if (Status.SUCCESS.equals(notification.getRefundStatus() )) {
            paymentService.updatePaymentStatusByOrderNo(notification.getOutTradeNo(), 3);
            updateOrdersStatus(notification.getOutTradeNo(), OrdersStatusEnum.ORDER_REFUND);
            log.info("---------退款成功的回调----SUCCESS" );
        }
    }

    public OrdersEntity updateOrdersStatus(String orderNo, OrdersStatusEnum type) {
        OrdersEntity orders = ordersMapper.selectOne(new LambdaQueryWrapper<OrdersEntity>().eq(OrdersEntity::getOrderNo, orderNo));

        if (orders.getStatus() != type) {
            orders.setStatus(type);
            ordersMapper.updateById(orders);
            log.info("---------订单状态更新成功----orders");
            return orders;
        }
        return orders;
    }
}
